-module('ShiftCipher').
-export([encrypt/3, decrypt/3]).

encrypt(Key, Filename, CopyFilename) when is_integer(Key), Key >= 0, Key =< 25 ->
    case openFiles(Filename, CopyFilename) of
	{ok,IoDeviceFrom, IoDeviceTo} ->
	    encryptFile(Key, IoDeviceFrom, IoDeviceTo);
	{error, Reason} ->
	    {encrypt_error, Reason}
    end.

encryptFile(Key, IoDeviceFrom, IoDeviceTo) ->
    case file:read(IoDeviceFrom, 1) of
	{ok, [Data]} -> 	    
	    try file:write(IoDeviceTo, [encryptUnit(Data, Key)]) of
		ok -> 
		    encryptFile(Key, IoDeviceFrom, IoDeviceTo);
		{error, Reason} -> 
		    {error, Reason}
	    catch
		error:_Error -> 
		    {problem, 'imposible to encrypt unit (skipping it)'}
	    end;
	eof -> 
	    closeFiles(IoDeviceFrom,IoDeviceTo)
	end.

decrypt(Key, Filename, CopyFilename) when is_integer(Key), Key >= 0, Key =< 25 ->
    case openFiles(Filename, CopyFilename) of
	{ok,IoDeviceFrom, IoDeviceTo} ->
	    decryptFile(Key, IoDeviceFrom, IoDeviceTo);
	{error, Reason} ->
	    {encrypt_error, Reason}
    end.

decryptFile(Key, IoDeviceFrom, IoDeviceTo) ->
    case file:read(IoDeviceFrom, 1) of
	{ok, [Data]} -> 	    
	    try file:write(IoDeviceTo, [decryptUnit(Data, Key)]) of
		ok -> 
		    decryptFile(Key, IoDeviceFrom, IoDeviceTo);
		{error, Reason} -> 
		    {error, Reason}
	    catch
		error:_Error -> 
		    {problem, 'imposible to decrypt unit (skipping it)'}
	    end;
	eof -> 
	    closeFiles(IoDeviceFrom,IoDeviceTo)
    end.

openFiles(Filename, CopyFilename) ->
    case {file:open(Filename, read), file:open(CopyFilename, write)} of
	{{ok, IoDeviceFrom},{ok,IoDeviceTo}} -> 
	    {ok,IoDeviceFrom, IoDeviceTo} ; 
	{{error, Reason},_} -> 
	    {error, Reason};
	{_,{error, Reason}} -> 
	    {error, Reason}
    end.    

closeFiles(IoDevice1, IoDevice2) ->
    case {file:close(IoDevice1),file:close(IoDevice2)} of
	{ok,ok} ->
	    ok;
	{{error, Reason},_} -> 
	    {error, Reason};
	{_,{error, Reason}} -> 
	    {error, Reason}
    end.



encryptUnit(MessageUnit, Key) when is_integer(MessageUnit) , MessageUnit >= $A, MessageUnit =< $Z ->
    Unit = (((MessageUnit - 65) + Key) rem 26 ),
    if
	Unit >=0 -> Unit + 65;
	Unit <0  -> Unit + 26 + 65
    end.

decryptUnit(MessageUnit, Key) when is_integer(MessageUnit) , MessageUnit >= $A, MessageUnit =< $Z ->
    Unit = (((MessageUnit - 65) - Key) rem 26 ),
    if
	Unit >=0 -> Unit + 65;
	Unit <0  -> Unit + 26 + 65
    end.


